package com.cq.hd.admin.base;

import com.cq.hd.common.exception.BusinessException;
import com.cq.hd.common.response.Result;
import com.cq.hd.common.response.ResultGenerator;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.ShiroException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@RestControllerAdvice
public class ExceptionController {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object validException(MethodArgumentNotValidException exception) {
        return ResultGenerator.error(500, exception.getBindingResult().getAllErrors().stream()
                .map(ObjectError::getDefaultMessage).collect(Collectors.joining(",")));
    }

    @ExceptionHandler(BindException.class)
    public Object validException(BindException exception) {
        return ResultGenerator.error(500, exception.getAllErrors().stream()
                .map(ObjectError::getDefaultMessage).collect(Collectors.joining(",")));
    }

    @ExceptionHandler(value = ConstraintViolationException.class)
    public Object exceptionHandler(ConstraintViolationException exception) {
        Set<ConstraintViolation<?>> constraintViolations = exception.getConstraintViolations();
        Iterator<ConstraintViolation<?>> iterator = constraintViolations.iterator();
        List<String> msgList = new ArrayList<>();
        while (iterator.hasNext()) {
            ConstraintViolation<?> constraintViolation = iterator.next();
            msgList.add(constraintViolation.getMessageTemplate());
        }

        return ResultGenerator.error(500, msgList.toString());
    }

    // 捕捉shiro的异常
    @ExceptionHandler(ShiroException.class)
    public Object handle401() {
        return ResultGenerator.error(401, "您没有权限访问");
    }

    @ExceptionHandler(value = BusinessException.class)
    public Result<Object> handler(BusinessException ex) {
        log.error("ExceptionHandle捕获到BusinessException：{}, 堆栈信息：{}", ex.getMessage(), ex.getStackTrace());
        return ResultGenerator.error(ex.getCode(), ex.getMessage());
    }

    // 捕捉其他所有异常
    @ExceptionHandler(Exception.class)
    public Object globalException(HttpServletRequest request, Throwable ex) {
        log.error(ex.getMessage(), ex);
        return ResultGenerator.error(500, ex.getMessage());
    }

    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return HttpStatus.valueOf(statusCode);
    }

}
